Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

makefiles/suit: store public keys, make it easier to work with multiple keys #20858

Merged
merged 3 commits into from
Sep 13, 2024

Conversation

benpicco
Copy link
Contributor

@benpicco benpicco commented Sep 9, 2024

Contribution description

This makes it easier to work with encrypted keys and multiple keys. The firmware binary can contain multiple public keys that are used to verify the manifest.
The use case is that we want to include the production public key in the debug build, so we can seamlessly update to the production version without re-flashing the device.

If the public keys is always generated on the fly, this would still require the production key password even for the debug build.

Instead if we store the (unencrypted) public key, we can always include it in the debug build.

Testing procedure

  • create a 2nd, encrypted signature key, call it prod.pem
  • build examples/suit_update with make SUIT_KEY="default prod"

OpenSSL only asks for the passwort to create the public key once, then the firmware can be build without needing to decrypt the production key.

contents of generated riotbuild/public_key.h

const uint8_t public_key[][32] = {
 {
  0x91, 0x6e, 0xc8, 0xf1, 0x5b, 0x8a, 0x30, 0x84, 0x31, 0x1c, 0xd3, 0xf8,
  0xe4, 0xdf, 0xc3, 0x50, 0x11, 0xd6, 0x67, 0xc5, 0x1c, 0x2c, 0x6a, 0x30,
  0x03, 0x58, 0x96, 0x75, 0x8c, 0x33, 0x49, 0x8c
 },
 {
  0xba, 0x0c, 0x4f, 0x89, 0x7d, 0x5f, 0x3f, 0x5c, 0x41, 0x9c, 0xde, 0xd0,
  0x57, 0xa6, 0xbc, 0x56, 0xeb, 0xcc, 0xe3, 0x6f, 0x70, 0x50, 0x70, 0x6d,
  0x46, 0x00, 0x33, 0xeb, 0x76, 0xa9, 0x6a, 0xfd
 },
};

Only when the firmware is published (signed) the password for the production key needs to be entered.

Issues/PRs references

@github-actions github-actions bot added the Area: build system Area: Build system label Sep 9, 2024
@benpicco benpicco force-pushed the suit_multi_key-2 branch 2 times, most recently from 3f839d4 to db70fa0 Compare September 9, 2024 22:02
@benpicco benpicco added Type: enhancement The issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR labels Sep 9, 2024
@benpicco benpicco requested a review from fabian18 September 9, 2024 22:03
@riot-ci
Copy link

riot-ci commented Sep 9, 2024

Murdock results

✔️ PASSED

765dd68 makefiles/suit: use OpenSSL to generate key

Success Failures Total Runtime
10197 0 10197 17m:19s

Artifacts

@benpicco benpicco requested a review from bergzand September 10, 2024 08:22
@fabian18
Copy link
Contributor

Cool feature.
I think the testing procedure assumes that default.pem already exists.
If I delete it and do SUIT_KEY="default prod" make -C examples/suit_update, I think what happens on key generation
is that the second key is taken as the password of the first key.

Maybe this is simply a case of bad usage but was still kind of unexpected to me.

@benpicco
Copy link
Contributor Author

heh, good catch!
that's because suit/gen_key.py takes the 2nd argument as key. When using the make target instead of $(SUIT_SEC) (which is wrong with multiple keys anyway) things work as expected.

We might also just replace that call to the 'custom' Python script with another OpenSSL invocation.

This makes it easier to work with encrypted keys and multiple keys.
The firmware binary can contain multiple public keys that are used
to verify the manifest.
The use case is that we want to include the production public key
in the debug build, so we can seamlessly update to the production
version without re-flashing the device.

If the public keys is always generated on the fly, this would still
require the production key password even for the debug build.

Instead if we store the (unencrypted) public key, we can always
include it in the debug build.
makefiles/suit.inc.mk Outdated Show resolved Hide resolved
Copy link
Contributor

@fabian18 fabian18 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make -C examples/suit_update clean suit/publish SUIT_KEY="default prod" SUIT_KEY_SIGN=prod SUIT_SEC_PASSWORD=123456789

make: Entering directory '/home/fabian.huessler@ml-pa.loc/RIOT/examples/suit_update'
rm -rf /home/fabian.huessler@ml-pa.loc/RIOT/bootloaders/riotboot/bin/samr21-xpro/pkg-build/cmsis
# Reset package to checkout state.
rm -rf /home/fabian.huessler@ml-pa.loc/RIOT/build/pkg/c25519
rm -rf /home/fabian.huessler@ml-pa.loc/RIOT/examples/suit_update/bin/samr21-xpro/pkg-build/cmsis
rm -rf /home/fabian.huessler@ml-pa.loc/RIOT/examples/suit_update/bin/samr21-xpro/pkg-build/libcose
rm -rf /home/fabian.huessler@ml-pa.loc/RIOT/examples/suit_update/bin/samr21-xpro/pkg-build/nanocbor
compiling /home/fabian.huessler@ml-pa.loc/RIOT/dist/tools/riotboot_gen_hdr/bin/genhdr...
make: Nothing to be done for 'all'.
suit: generating key in /home/fabian.huessler@ml-pa.loc/.local/share/RIOT/keys
0) none
1) aes-256-cbc
Choose encryption for key file /home/fabian.huessler@ml-pa.loc/.local/share/RIOT/keys/prod.pem: 1
Enter PEM pass phrase:
Verifying - Enter PEM pass phrase:
read EC key
Enter pass phrase for /home/fabian.huessler@ml-pa.loc/.local/share/RIOT/keys/prod.pem:
writing EC key
read EC key
writing EC key
read EC key
writing EC key
test "dbfb4285837ab2ea3d99c448b22877cc7a139ccbaebb1de367e2bec1fd562fe629b389d86603915448078b8fd7e631c8fc9a7d126eb889a1ba0c17611369b190  /home/fabian.huessler@ml-pa.loc/RIOT/build/pkg/c25519-2017-10-05.zip" =  "$(sha512sum "/home/fabian.huessler@ml-pa.loc/RIOT/build/pkg/c25519-2017-10-05.zip")"
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/pkg/c25519/ 
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/build/pkg/c25519/src -f /home/fabian.huessler@ml-pa.loc/RIOT/Makefile.base MODULE=c25519
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/pkg/cmsis/ 
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/pkg/libcose/ 
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/build/pkg/libcose/src -f /home/fabian.huessler@ml-pa.loc/RIOT/Makefile.base MODULE=libcose
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/build/pkg/libcose/src/crypt -f /home/fabian.huessler@ml-pa.loc/RIOT/pkg/libcose/Makefile.libcose_crypt
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/pkg/nanocbor/ 
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/build/pkg/nanocbor/src -f /home/fabian.huessler@ml-pa.loc/RIOT/Makefile.base MODULE=nanocbor
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/boards/common/init
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/boards/samr21-xpro
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/core
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/core/lib
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/cpu/samd21
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/cpu/cortexm_common
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/cpu/cortexm_common/periph
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/cpu/sam0_common
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/cpu/sam0_common/periph
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/cpu/samd21/periph
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/cpu/samd21/vectors
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/drivers
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/drivers/edbg_eui
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/drivers/ethos
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/drivers/netdev
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/drivers/periph_common
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/pkg/libcose/init
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/auto_init
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/checksum
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/crypto
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/div
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/event
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/evtimer
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/fmt
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/frac
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/hashes
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/iolist
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/isrpipe
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/libc
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/luid
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/malloc_thread_safe
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/net/application_layer/nanocoap
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/net/application_layer/uhcp
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/net/crosslayer/inet_csum
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/net/gnrc
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/net/gnrc/netapi
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/net/gnrc/netif
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/net/gnrc/netif/ethernet
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/net/gnrc/netif/hdr
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/net/gnrc/netif/init_devs
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/net/gnrc/netreg
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/net/gnrc/network_layer/icmpv6
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/net/gnrc/network_layer/icmpv6/echo
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/net/gnrc/network_layer/ipv6
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/net/gnrc/network_layer/ipv6/hdr
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/net/gnrc/network_layer/ipv6/nib
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/net/gnrc/network_layer/ndp
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/net/gnrc/pkt
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/net/gnrc/pktbuf
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/net/gnrc/pktbuf_static
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/net/gnrc/sock
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/net/gnrc/sock/udp
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/net/gnrc/transport_layer/udp
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/net/gnrc/application_layer/uhcpc
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/net/link_layer/eui_provider
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/net/link_layer/l2util
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/net/netif
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/net/netutils
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/net/network_layer/icmpv6
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/net/network_layer/ipv6/addr
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/net/network_layer/ipv6/hdr
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/net/sock
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/net/transport_layer/udp
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/newlib_syscalls_default
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/pm_layered
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/posix/inet
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/preprocessor
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/progress_bar
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/random
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/riotboot
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/shell
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/shell/cmds
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/suit
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/suit/storage
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/suit/transport
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/test_utils/interactive_sync
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/tiny_strerror
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/tsrb
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/uuid
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/vfs
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/vfs_util
"make" -C /home/fabian.huessler@ml-pa.loc/RIOT/sys/ztimer
creating /home/fabian.huessler@ml-pa.loc/RIOT/examples/suit_update/bin/samr21-xpro/riotboot_files/slot0.1726166621.bin...
creating /home/fabian.huessler@ml-pa.loc/RIOT/examples/suit_update/bin/samr21-xpro/riotboot_files/slot1.1726166621.bin...
published "/home/fabian.huessler@ml-pa.loc/RIOT/examples/suit_update/bin/samr21-xpro/suit_files/riot.suit.1726166621.bin"
       as "coap://localhost/fw/suit_update/samr21-xpro/riot.suit.1726166621.bin"
published "/home/fabian.huessler@ml-pa.loc/RIOT/examples/suit_update/bin/samr21-xpro/suit_files/riot.suit.latest.bin"
       as "coap://localhost/fw/suit_update/samr21-xpro/riot.suit.latest.bin"
published "/home/fabian.huessler@ml-pa.loc/RIOT/examples/suit_update/bin/samr21-xpro/riotboot_files/slot0.1726166621.bin"
       as "coap://localhost/fw/suit_update/samr21-xpro/slot0.1726166621.bin"
published "/home/fabian.huessler@ml-pa.loc/RIOT/examples/suit_update/bin/samr21-xpro/riotboot_files/slot1.1726166621.bin"
       as "coap://localhost/fw/suit_update/samr21-xpro/slot1.1726166621.bin"
make: Leaving directory '/home/fabian.huessler@ml-pa.loc/RIOT/examples/suit_update'
const uint8_t public_key[][32] = {
 {
  0xad, 0x7f, 0x4e, 0xc2, 0xd5, 0x0b, 0xa3, 0xb3, 0xef, 0x8f, 0x7a, 0xc5,
  0xa6, 0x73, 0xcc, 0x4a, 0xf5, 0x01, 0x30, 0xae, 0x6a, 0x58, 0xf8, 0xce,
  0xd4, 0xcf, 0x8e, 0xf9, 0x3f, 0xc6, 0xc8, 0x92
 },
 {
  0x18, 0xcb, 0x23, 0x9f, 0x6c, 0xd6, 0x82, 0xae, 0x7f, 0xbd, 0x77, 0xc1,
  0x4a, 0x9b, 0x04, 0x33, 0xa4, 0xce, 0x99, 0xb6, 0x12, 0x92, 0x38, 0x5b,
  0x1d, 0xdf, 0xd4, 0x87, 0x67, 0x2c, 0x4d, 0xed
 },
};

Co-authored-by: Fabian Hüßler <fabian.huessler@ml-pa.com>
@benpicco benpicco added this pull request to the merge queue Sep 12, 2024
@benpicco
Copy link
Contributor Author

Thank you for the review!

Merged via the queue into RIOT-OS:master with commit 870fe04 Sep 13, 2024
25 checks passed
@benpicco benpicco deleted the suit_multi_key-2 branch September 13, 2024 06:52
@benpicco benpicco added this to the Release 2024.10 milestone Nov 27, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: build system Area: Build system CI: ready for build If set, CI server will compile all applications for all available boards for the labeled PR Type: enhancement The issue suggests enhanceable parts / The PR enhances parts of the codebase / documentation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants